/*
 *
 *  * Copyright (c) iwindplus Technologies Co., Ltd.2024-2030, All rights reserved.
 *
 *
 */

package com.iwindplus.base.async.cmd.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.github.yulichang.repository.JoinCrudRepository;
import com.iwindplus.base.async.cmd.domain.dto.AsyncCmdEditDTO;
import com.iwindplus.base.async.cmd.domain.dto.AsyncCmdSaveDTO;
import com.iwindplus.base.async.cmd.domain.enums.CmdStatusEnum;
import com.iwindplus.base.async.cmd.mapper.AsyncCmdMapper;
import com.iwindplus.base.async.cmd.model.AsyncCmdDO;
import com.iwindplus.base.async.cmd.service.AsyncCmdService;
import com.iwindplus.base.domain.enums.BizCodeEnum;
import com.iwindplus.base.domain.exception.BizException;
import com.iwindplus.base.util.JacksonUtil;
import java.util.List;
import java.util.Objects;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 异步命业务层接口实现类.
 *
 * @author zengdegui
 * @since 2018/9/1
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class AsyncCmdServiceImpl extends JoinCrudRepository<AsyncCmdMapper, AsyncCmdDO> implements AsyncCmdService {

    @Override
    public boolean save(AsyncCmdSaveDTO entity) {
        // 如果业务流水号为空，则生成一个
        if (CharSequenceUtil.isBlank(entity.getBizNumber())) {
            entity.setBizNumber(DigestUtil.md5Hex(JacksonUtil.toJsonStr(entity)));
        }
        this.getBizNumberIsExist(entity.getBizNumber().trim(), entity.getCmdType());

        entity.setCmdStatus(CmdStatusEnum.INIT);
        final AsyncCmdDO model = BeanUtil.copyProperties(entity, AsyncCmdDO.class);
        super.save(model);
        entity.setId(model.getId());
        return Boolean.TRUE;
    }

    @Override
    public boolean removeByIds(List<Long> ids) {
        return super.removeByIds(ids);
    }

    @Override
    public boolean edit(AsyncCmdEditDTO entity) {
        AsyncCmdDO data = super.getById(entity.getId());
        if (Objects.isNull(data)) {
            throw new BizException(BizCodeEnum.DATA_NOT_EXIST);
        }
        if (CharSequenceUtil.isNotBlank(entity.getBizNumber()) && !CharSequenceUtil.equals(data.getBizNumber(), entity.getBizNumber().trim())) {
            this.getBizNumberIsExist(entity.getBizNumber().trim(), entity.getCmdType());
        }
        if (Objects.isNull(entity.getVersion())) {
            entity.setVersion(data.getVersion());
        }
        final AsyncCmdDO model = BeanUtil.copyProperties(entity, AsyncCmdDO.class);
        super.updateById(model);
        return Boolean.TRUE;
    }

    @Override
    public boolean editBatch(List<AsyncCmdEditDTO> entities, int batchSize) {
        if (CollUtil.isEmpty(entities)) {
            return Boolean.FALSE;
        }

        List<AsyncCmdDO> doList = BeanUtil.copyToList(entities, AsyncCmdDO.class);
        super.updateBatchById(doList, batchSize);
        return Boolean.TRUE;
    }

    private void getBizNumberIsExist(String bizNumber, String cmdType) {
        final LambdaQueryWrapper<AsyncCmdDO> queryWrapper = Wrappers.lambdaQuery(AsyncCmdDO.class)
            .eq(AsyncCmdDO::getBizNumber, bizNumber)
            .eq(AsyncCmdDO::getCmdType, cmdType);
        boolean result = SqlHelper.retBool(super.count(queryWrapper));
        if (Boolean.TRUE.equals(result)) {
            throw new BizException(BizCodeEnum.BIZ_NUMBER_EXIST, new Object[]{bizNumber});
        }
    }
}
